<HTML>
<!--
	THE JAVASCRIPT COOKBOOK by Erica Sadun, webrx@mindspring.com
								J. Brook Monroe, mrprogguy@techie.com
    Copyright (c)1998 by Charles River Media.  All Rights Reserved.
    
    This applet can only be re-used or modifed by license holders of the
    JavaScript Cookbook CD-ROM.  Credit must be given in the source
    code and this copyright notice must be maintained. If you do
    not hold a license to the JavaScript Cookbook, you may NOT
    duplicate or modify this code for your own use.

	Use at your own risk. No warranty is given or implied of the suitability 
	of this applet for any specific application. Neither Erica Sadun,
	J. Brook Monroe nor Charles River Media will be held responsible for any
	unwanted effects due to the use of this applet or any derivative. 
-->	
<HEAD>
	<TITLE>Sorting an Array</TITLE>
</HEAD>
<SCRIPT LANGUAGE="JavaScript1.2"><!--
var myArray;

function CompareNumbers(a,b)
{
	return a - b;
}

function ArrayOnlyNumbers()
{
	for(var i = 0; i < myArray.length; i++) {
		// If it's not an integer, bail out
		if(isNaN(parseInt(myArray[i])))
			return false;
		// If it's not a floating point number, bail out
		if(isNaN(parseFloat(myArray[i])))
			return false;
	}
	// Must consist only of numbers!
	return true;
}

function Go()
{
	var i;
	for(i = 0; i < 8; i++)
		myArray[i] = eval("document.forms[0].slot"+i+".value");
	if(ArrayOnlyNumbers())
		myArray.sort(CompareNumbers);
	else		
		myArray.sort();
	for(i = 0; i < 8; i++)
		eval("document.forms[0].out"+i+".value='"+myArray[i]+"'");
}

function Warning(cellId)
{
	eval("document.forms[1].out"+cellId+".value=''");
	alert("No, you shouldn't type in that cell!");
}
myArray = new Array(8);
//-->
</SCRIPT>
<BODY>
<FONT COLOR="007777"><H1><IMG SRC="../GRAFX/UTENS.JPG" WIDTH=80 HEIGHT=50
ALIGN = LEFT>Sort an Array</H1></FONT>
<BLOCKQUOTE><FONT COLOR="770000">
In this recipe we find out that JavaScript in Navigator can sort arrays for us.
</FONT><P>
Fill in the top row of boxes and press the "GO!" button.<BR>
<FORM>
Unsorted:<BR>
<INPUT TYPE="text" VALUE="" NAME="slot0" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot1" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot2" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot3" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot4" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot5" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot6" SIZE=8>
<INPUT TYPE="text" VALUE="" NAME="slot7" SIZE=8>
<INPUT TYPE="button" VALUE="GO!" onClick="Go()"><BR>
Sorted:<BR>
<INPUT TYPE="text" VALUE="" NAME="out0" SIZE=8 onChange="Warning(0)">
<INPUT TYPE="text" VALUE="" NAME="out1" SIZE=8 onChange="Warning(1)">
<INPUT TYPE="text" VALUE="" NAME="out2" SIZE=8 onChange="Warning(2)">
<INPUT TYPE="text" VALUE="" NAME="out3" SIZE=8 onChange="Warning(3)">
<INPUT TYPE="text" VALUE="" NAME="out4" SIZE=8 onChange="Warning(4)">
<INPUT TYPE="text" VALUE="" NAME="out5" SIZE=8 onChange="Warning(5)">
<INPUT TYPE="text" VALUE="" NAME="out6" SIZE=8 onChange="Warning(6)">
<INPUT TYPE="text" VALUE="" NAME="out7" SIZE=8 onChange="Warning(7)">
</FORM>
<FONT COLOR="007777"><H2>Discussion</H2></FONT>
<FONT SIZE=4>
Like the array reversal discussion, this too can be easily summed up:  which would you rather write (and maintain)?
<H3><FONT COLOR="007777">The Hard Way</FONT></H3>
<FONT COLOR="770000"><PRE>
function sort(anArray,lft,rgt)
{
  var i,j,x,y;
  i = lft;
  j = rgt;
  x = anArray[Math.floor((lft + rgt) / 2)];
  do {
    while(anArray[i] < x)
      i += 1;
    while(x < anArray[j])
      j -= 1;
    if(i <= j) {
        y = anArray[i];
        anArray[i] = anArray[j];
        anArray[j] = y;
        i += 1;
        j -= 1;
    }
  } while(i <= j);
  if (lft < j)
  	sort(lft,j);
  if(i < r)
  	sort(i,rgt);
}

function qsort(anArray,lo,hi)
{
  sort(anArray,lo,hi);
}

</PRE></FONT>
<H3><FONT COLOR="007777">The Easy Way</FONT></H3>
<FONT COLOR="770000"><PRE>anArray.sort();</PRE></FONT>
We cheated a little in the code fragments.  The process of sorting an array can be more complicated
than just calling <FONT COLOR="770000">sort()</FONT>.  Compare the first sorted list to the second:<P>
<FONT FACE="Arial,Helvetica" SIZE=3>1,2,3,4,5,6,7,8,9,10,11,12<BR>
1,10,11,12,2,3,4,5,6,7,8,9<P></FONT>
You're probably thinking that the second one is sorted out-of-order.  That really isn't true, though.  The
second list is sorted <i>lexicographically</i> (as a string value) rather than <i>numerically</i> (by
the value that the character string represents).  Since the character "1" has a slower sorting value
than the character "2," anything starting with "1" in the second list sorts out before anything starting
with "2" or greater.<p>
By default, <FONT COLOR="770000">sort()</FONT> works lexicographically.  This isn't much help if what you've
got to sort is numbers.  Luckily, you can test an array to see if it's all numbers, and act accordingly.  Here's a 
code fragment from this recipe:
<FONT COLOR="770000"><PRE>
	if(ArrayOnlyNumbers())
		myArray.sort(CompareNumbers);
	else		
		myArray.sort();
</PRE></FONT>
Right away you will have noticed that there's two different ways to call <FONT COLOR="770000">sort()</FONT>: with
an argument and without. When you supply an argument, it's the name of a function which will be used to compare
elements in the array (more about this later).<p>
The code fragment above tries to select the proper kind of sort to perform.  A strictly numeric array will be
numerically sorted, and a string, or mixed string-and-number array will be sorted lexicographically.  (View the source
to see how <FONT COLOR="007777">ArrayOnlyNumbers()</FONT> makes its decision.)<p>
The <FONT COLOR="770000">sort()</FONT> function requires the user-written compare function to take two arguments and
returns a value according to the following rules [keep <FONT COLOR="007777">compareFunc(a,b)</FONT> in mind]:<p>
<UL>
	<LI>If <FONT COLOR="007777">b</FONT> sorts before <FONT COLOR="007777">a</FONT>, return a value less than zero.</LI>
	<LI>If <FONT COLOR="007777">b</FONT> sorts the same as <FONT COLOR="007777">a</FONT>, return zero.</LI>
    <LI>If <FONT COLOR="007777">b</FONT> sorts after <FONT COLOR="007777">a</FONT>, return a value greater than zero.</LI>
</UL>	
You can write the comparison function to sort along any criteria you might have.  The result of the comparison
doesn't need to rely on such simple rules as lexical or numerical comparison of an entire string or number.  You can
compare substrings, last digits, or anything else you require to get the job done.
</FONT>
<BR><BR><h5>Copyright ©1998 by Charles River Media, All Rights Reserved</h5>
</BODY>
</HTML>